package org.luxor.cloud.gateway.component;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.ArrayType;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * Jackson2 Json转换工具类
 *
 * @author Mr.Yan  @date: 2020/11/12
 */
public class Jackson2Mapper {
    private static final ObjectMapper objectMapper;

    static {
        // 解决long类型精度丢失问题
        objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(BigInteger.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        // 设置为空的字段不返回
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 反序列化时候，忽略多余的字段
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 忽略空Bean转Json的错误
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 指定json转换时间类型的时区
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        // 指定返回的时间格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     * 对象转换为JsonText
     */
    public static String toJson(Object object) throws JsonProcessingException {
        if (object == null) {
            return null;
        }
        return objectMapper.writeValueAsString(object);
    }

    /**
     * 对象转换为格式化的JsonText
     */
    public static String toJsonPretty(Object object) throws JsonProcessingException {
        return StringUtils.replace(toJson(object), "\t", "  ");
    }

    /**
     * JsonText转换为JavaBean
     */
    public static <T> T toBean(String jsonText, Class<T> clazz) throws JsonProcessingException {
        if (StringUtils.isBlank(jsonText) || clazz == null) {
            return null;
        }
        try {
            return objectMapper.readValue(jsonText, clazz);
        } catch (IOException e) {
            throw JsonMappingException.fromUnexpectedIOE(e);
        }
    }

    /**
     * JsonText转换为JavaBean
     */
    public static <T> T toBean(InputStream content, Class<T> clazz) throws JsonProcessingException {
        if (content == null || clazz == null) {
            return null;
        }
        try {
            return objectMapper.readValue(content, clazz);
        } catch (IOException e) {
            throw JsonMappingException.fromUnexpectedIOE(e);
        }
    }

    /**
     * 转换为数组
     */
    public static <T> T[] toArray(String jsonText, Class<T> clazz) throws JsonProcessingException {
        if (jsonText == null || clazz == null) {
            return null;
        }
        try {
            ArrayType arrayType = objectMapper.getTypeFactory().constructArrayType(clazz);
            return objectMapper.readValue(jsonText, arrayType);
        } catch (IOException e) {
            throw JsonMappingException.fromUnexpectedIOE(e);
        }
    }

    /**
     * 转换为List
     */
    public static <T> List<T> toList(String jsonText, Class<T> clazz) throws JsonProcessingException {
        if (jsonText == null || clazz == null) {
            return null;
        }
        try {
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
            return objectMapper.readValue(jsonText, collectionType);
        } catch (IOException e) {
            throw JsonMappingException.fromUnexpectedIOE(e);
        }
    }

    /**
     * 转换为Map
     */
    public static <T> Map<String, T> toMap(String jsonText, Class<T> clazz) throws JsonProcessingException {
        if (jsonText == null) {
            return null;
        }
        try {
            MapType mapType = objectMapper.getTypeFactory().constructMapType(Map.class, String.class, clazz);
            return objectMapper.readValue(jsonText, mapType);
        } catch (IOException e) {
            throw JsonMappingException.fromUnexpectedIOE(e);
        }
    }

}
